/*
 * PhotonRTOS础光实时操作系统 -- 双向链表头文件
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Baoyou Xie <xiebaoyou@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#ifndef _OS_LIST_H
#define _OS_LIST_H

#include <photon/types.h>
#include <photon/magic.h>
#include <photon/kernel.h>

#define LIST_HEAD_INITIALIZER(name) { &(name), &(name) }

static inline void list_init(struct double_list *list)
{
	list->next = list;
	list->prev = list;
	list->is_list = 999;
}

static inline int32_t list_is_empty(const struct double_list *head)
{
	return head->next == head;
}

static inline void __list_insert(struct double_list *new,
				struct double_list *prev,
				struct double_list *next)
{
	next->prev = new;
	new->next = next;
	new->prev = prev;
	prev->next = new;
}

static inline void list_insert_front(struct double_list *new,
		struct double_list *head)
{
	__list_insert(new, head, head->next);
}

static inline void list_insert_behind(struct double_list *new,
		struct double_list *head)
{
	__list_insert(new, head->prev, head);
}

static inline void __list_link(struct double_list *prev,
		struct double_list *next)
{
	next->prev = prev;
	prev->next = next;
}

static inline void __list_del_entry(struct double_list *entry)
{
	__list_link(entry->prev, entry->next);
}

static inline void list_del(struct double_list *entry)
{
	__list_link(entry->prev, entry->next);
	entry->next = LIST_UNLINK1;
	entry->prev = LIST_UNLINK2;
}

static inline void list_del_init(struct double_list *entry)
{
	__list_del_entry(entry);
	list_init(entry);
}

static inline void list_move_to_behind(struct double_list *list,
				  struct double_list *head)
{
	__list_del_entry(list);
	list_insert_behind(list, head);
}

#define list_container(ptr, type, member)				\
	container_of(ptr, type, member)

#define list_first_container(ptr, type, member)				\
	list_container((ptr)->next, type, member)

#define list_last_container(ptr, type, member)				\
	list_container((ptr)->prev, type, member)

#define list_next_entry(pos, member)					\
	list_container((pos)->member.next, typeof(*(pos)), member)

#define list_for_each(pos, head)					\
	for (pos = (head)->next; pos != (head); pos = pos->next)

#define list_for_each_safe(pos, n, head)				\
	for (pos = (head)->next, n = pos->next; pos != (head);		\
		pos = n, n = pos->next)

#define list_for_each_entry(pos, head, member)				\
	for (pos = list_first_container(head, typeof(*pos), member);	\
		&pos->member != (head);					\
		pos = list_next_entry(pos, member))

#define list_for_each_prev(pos, head)					\
	for (pos = (head)->prev; pos != (head); pos = pos->prev)
#endif /* _OS_LIST_H */
